概述 在正常的iOS系统下,由于沙盒与随机地址的分配的作用下,应用数据的安全是没有问题的,但是在越狱情况下,应用间的数据是共享的,这就存在安全问题,同时也存在手机失窃,面临取证攻击(主要),所以我们在存储敏感数据时要格外小心.
防止数据泄露的方法 正式版禁用NSLog/Print NSLog方法本质并非向控制台输出调试信息,而是向苹果系统日志(Apple System Log)中输出错误信息,官方解释为
服务器接收到的消息(被输入规则过滤后)会存放在数据仓库(data store)中,该API允许客户端创建查询并搜索消息数据仓库中满足条件的消息.
换句话说可以把NSLog看做printf和syslog的结合体,在调试时将消息发送到Xcode控制台,在设备上运行时将消息发送到系统全局日志.而且此数据外界很容易获得,只需要从Xocde Window->Devices and Simulator 中就可以获得,例如我运行如下代码:
1 2 3 for (int i = 0; i<100; i++) { NSLog(@"hahhahahahahahahahaha"); }
查看日志:
所以在正式版中一定要禁用NSLog,以免意外.
HTTP缓存 URL加载系统会存储未加密的缓存数据,这些数据存储在Cache.db文件中.而这就会将一些敏感数据缓存在本地,导致不必要的安全风险. 这是一些清除缓存的API:
1 2 3 4 5 6 7 8 9 // 只会删除内存中的缓存 [[NSURLCache sharedURLCache] removeAllCachedResponses]; //限制缓存容量,然而该API并不能限制缓存, //此配置只能在内存/硬盘空间不够时给系统发挥作用. [[NSURLCache sharedURLCache] setDiskCapacity:0]; //设置Cache的缓存策略,并不能禁用缓存,而是在下次请求中不再使用缓存而已 manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
当我将上面三个方法都实现后,利用AFNetworking访问 https://www.baidu.com 时在沙盒中仍然有缓存的.
可以看到还是有缓存滴~ 那么该怎么办嘞~
取消缓存的方法
1,服务器返回响应头禁用缓存,Cache-Control: no-cache,no-store,must-revalidate 2,直接在Cache路径中 将缓存文件删除(粗暴有效)
截屏泄露 用户主动截屏并不是我要讨论的,我们可以在关键界面截屏后提示用户泄密风险(在iOS7后,只能在截屏后获得通知). iOS会在应用进入后台之前对当前应用状态截屏,当重新打开应用时可以生成过度动画,提高用户体验,然而有时这就会泄露关键信息.
解决方案:
在屏幕被截取前对显示图像进行处理(如加上高斯模糊),在进入应用时将高斯模糊图去掉.
而”截屏”事件发生在应用进入后台之后.所以可以在- (void)applicationDidEnterBackground:(UIApplication *)application
方法中实现高斯模糊操作.
钥匙串的使用 如果需要存储密码,个人资料等小段敏感数据,使用钥匙串最好不过了.我推荐使用 SSKeyChain 库,它对钥匙串的操作进行了面向对象的封装.主要有以下几个方法:
可以将 服务与账号看成不同的文件夹, 服务是行号的上级目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 返回本应用的所有钥匙串信息 [SSKeychain allAccounts]; //发挥指定服务下的所有钥匙串信息 [SSKeychain accountsForService:<#(NSString *)#>]; //获取指定服务,账号的密码 [SSKeychain passwordForService:<#(NSString *)#> account:<#(NSString *)#>]; //删除指定服务,账户的信息 [SSKeychain deletePasswordForService:<#(NSString *)#> account:<#(NSString *)#>]; //将密码保存到指定服务,账号中 [SSKeychain setPassword:<#(NSString *)#> forService:<#(NSString *)#> account:<#(NSString *)#>];
除此之外,还要设置钥匙串的保护属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 //设置钥匙串的保护属性,有以下几个选项 [SSKeychain setAccessibilityType:<#(CFTypeRef)#>]; //只有设备未被锁定时钥匙串就保持可用 extern const CFStringRef kSecAttrAccessibleWhenUnlocked __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); //开机之后使用者第一次输入密码后钥匙可用(锁屏也可以) extern const CFStringRef kSecAttrAccessibleAfterFirstUnlock __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); //钥匙串在始终可用 extern const CFStringRef kSecAttrAccessibleAlways __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); //只有设备设置密码才可用,且不可以移植到其他设备,一旦取消密码则存储信息会从设备中删除,且无备份(iOS8) extern const CFStringRef kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); //只有设备未被锁定时钥匙串就保持可用,且不可移植 extern const CFStringRef kSecAttrAccessibleWhenUnlockedThisDeviceOnly __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); //开机之后使用者第一次输入密码后钥匙可用(锁屏也可以),且不可移植 extern const CFStringRef kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); //钥匙串始终可用,且不可移植 extern const CFStringRef kSecAttrAccessibleAlwaysThisDeviceOnly __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0);
注意:
即使删除应用,钥匙串中的信息并不会删除,只有恢复出厂设置才会删除. keychain sharing可以进行钥匙串共享 是指同一家公司的同一个开发者账号开发的不同APP之间的钥匙串信息共享
数据保护API 苹果公司推出数据保护API,它允许开发者指定文件解密秘钥的生命周期.数据保护API使用用户密码和层级秘钥来加密保护文件的秘钥.作用上就像钥匙串那样保护文件.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 //对options进行配置,设置文件保护级别 NSData* data = [NSData new]; [data writeToFile:@"" options:(NSDataWritingOptions) error:nil]; typedef NS_OPTIONS(NSUInteger, NSDataWritingOptions) { NSDataWritingAtomic = 1UL << 0, // Hint to use auxiliary file when saving; equivalent to atomically:YES NSDataWritingWithoutOverwriting API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0)) = 1UL << 1, // Hint to prevent overwriting an existing file. Cannot be combined with NSDataWritingAtomic. NSDataWritingFileProtectionNone NS_ENUM_AVAILABLE_IOS(4_0) = 0x10000000, //Comeplete是当前最安全的文件保护等级,锁屏之后文件会不可读. NSDataWritingFileProtectionComplete NS_ENUM_AVAILABLE_IOS(4_0) = 0x20000000, //如果文件被当前应用打开,那会暂时禁用该文件的保护,会确保该文件在锁屏时依旧可以写入.若想在锁屏之后再去打开则不可以. NSDataWritingFileProtectionCompleteUnlessOpen NS_ENUM_AVAILABLE_IOS(5_0) = 0x30000000, NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication NS_ENUM_AVAILABLE_IOS(5_0) = 0x40000000, NSDataWritingFileProtectionMask NS_ENUM_AVAILABLE_IOS(4_0) = 0xf0000000, // Options with old names for NSData writing methods. Please stop using these old names. NSAtomicWrite = NSDataWritingAtomic // Deprecated name for NSDataWritingAtomic };
总结 从苹果提供的保护措施来看,它的保护措施几乎完全依赖于用户密码 这个体系,使用钥匙串和数据保护其实就是在沙盒保护的基础上,又加了一层保护而已. 在越狱的情况,或者锁屏密码遭到暴力破解.那么安全就不保了,因此我感觉意义不是那么大. 所以我认为可以将钥匙串理解为一个高级沙盒, 它有删除软件数据保留,和钥匙串分享的功能.
以我个人见解,对于移动端数据安全这里我认为需要这样做:
1, 避免数据泄露(如HTTP缓存….); 2, 自己加密,即便是在钥匙串中的密码也是加密过多.这样想要盗窃用户数据不仅要攻克设备密码 也要攻克我们的软件 这样更加安全.